########################################################################
#  Searx-qt - Lightweight desktop application for SearX.
#  Copyright (C) 2020  CYBERDEViL
#
#  This file is part of Searx-qt.
#
#  Searx-qt is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  Searx-qt is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
########################################################################

from PyQt5.QtWidgets import (
    QApplication,
    QAction,
    QSplitter,
    QMenuBar,
    QMenu,
    QMainWindow,
    QVBoxLayout,
    QWidget,
    QStatusBar,
    QLabel
)

from PyQt5.QtCore import Qt, QSettings, QByteArray, QSize

from searxqt.models.instances import (
    InstancesModel,
    InstanceModelFilter,
    InstanceSelecterModel
)

from searxqt.models.settings import SettingsModel
from searxqt.models.search import SearchModel

from searxqt.views.instances import InstancesView
from searxqt.views.settings import SettingsWindow
from searxqt.views.search import SearchContainer
from searxqt.views import about


class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        QMainWindow.__init__(self, *args, **kwargs)
        self.setWindowTitle("SearX-Qt")

        self.settings = QSettings('CYBERDEViL', 'searx-qt', self)
        self._settingsModel = SettingsModel(self)

        self._instancesModel = InstancesModel(
                requestSettings=self._settingsModel.requests, parent=self)
        self.instanceFilter = InstanceModelFilter(
            self._instancesModel, self)
        self.instanceSelecter = InstanceSelecterModel(self.instanceFilter)
        self._settingsWindow = None

        self._searchModel = SearchModel(self._settingsModel.requests, self)

        # -- Menu bar
        menubar = QMenuBar(self)

        # Menu file
        menuFile = QMenu(menubar)
        menuFile.setTitle("File")

        saveAction = QAction("Save", menuFile)
        menuFile.addAction(saveAction)
        saveAction.setShortcut('Ctrl+S')
        saveAction.triggered.connect(self.saveSettings)

        actionExit = QAction("Exit", menuFile)
        menuFile.addAction(actionExit)
        actionExit.setShortcut('Ctrl+Q')
        actionExit.triggered.connect(self.__quit)

        menubar.addAction(menuFile.menuAction())

        # Menu settings
        settingsAction = QAction("Settings", menubar)
        menubar.addAction(settingsAction)
        settingsAction.triggered.connect(self._openSettingsWindow)

        # Menu about dialog
        aboutAction = QAction("About", menubar)
        menubar.addAction(aboutAction)
        aboutAction.triggered.connect(self._openAboutDialog)

        self.setMenuBar(menubar)
        # -- End menu bar

        # -- Status bar
        self.statusBar = QStatusBar(self)

        self._statusInstanceLabel = QLabel(self)
        self.statusBar.addPermanentWidget(self._statusInstanceLabel)

        self.setStatusBar(self.statusBar)
        # -- End status bar

        centralWidget = QWidget(self)
        layout = QVBoxLayout(centralWidget)
        self.setCentralWidget(centralWidget)

        self.splitter = QSplitter(centralWidget)
        self.splitter.setOrientation(Qt.Horizontal)
        layout.addWidget(self.splitter)

        self.searchContainer = SearchContainer(
            self._searchModel, self.instanceFilter,
            self.instanceSelecter, self.splitter)
        self.instancesWidget = InstancesView(
            self.instanceFilter, self.instanceSelecter, self.splitter)

        self.instanceSelecter.instanceChanged.connect(self.__instanceChanged)

        self.resize(800, 600)
        self.loadSettings()

    def __quit(self):
        QApplication.quit()

    def __instanceChanged(self, url):
        self._statusInstanceLabel.setText("Instance: {0}".format(url))

    def closeEvent(self, event):
        self.saveSettings()
        QApplication.closeAllWindows()

    def _openAboutDialog(self):
        about.show(self)

    def _openSettingsWindow(self):
        if not self._settingsWindow:
            self._settingsWindow = SettingsWindow(self._settingsModel)
        self._settingsWindow.show()

    def loadSettings(self):
        self.resize(
            self.settings.value('windowSize', QSize(), QSize)
        )

        self.splitter.restoreState(
            self.settings.value('splitterState', QByteArray(), QByteArray)
        )

        self._instancesModel.loadSettings(
            self.settings.value('instancesData', dict(), dict)
        )

        self._settingsModel.loadSettings(
            self.settings.value('settingsRequests', dict(), dict)
        )

        self.instanceFilter.loadSettings(
            self.settings.value('instanceFilter', dict(), dict)
        )

        self.instancesWidget.loadSettings(
            self.settings.value('instancesView', dict(), dict)
        )

        # Load the instanceSelecter after the instancesView and
        # instanceFilter, they depend on it. (Connections are wired that
        # way)
        self.instanceSelecter.loadSettings(
            self.settings.value('instanceSelecter', dict(), dict)
        )

        self.searchContainer.loadSettings(
            self.settings.value('searchView', dict(), dict)
        )

        self._searchModel.loadSettings(
            self.settings.value('searchModel', dict(), dict)
        )

    def saveSettings(self):
        self.settings.setValue('windowSize', self.size())
        self.settings.setValue('splitterState', self.splitter.saveState())
        self.settings.setValue('instancesData', self._instancesModel.data())

        self.settings.setValue(
            'settingsRequests',
            self._settingsModel.saveSettings()
        )

        self.settings.setValue(
            'instanceFilter',
            self.instanceFilter.saveSettings()
        )

        self.settings.setValue(
            'instanceSelecter',
            self.instanceSelecter.saveSettings()
        )

        self.settings.setValue(
            'instancesView',
            self.instancesWidget.saveSettings()
        )

        self.settings.setValue(
            'searchView',
            self.searchContainer.saveSettings()
        )

        self.settings.setValue(
            'searchModel',
            self._searchModel.saveSettings()
        )
